// 银行同步

#include <stdio.h>
#include <pthread.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

typedef struct {
    int id;
    int banlance;
    //注意点2：选择合适粒度的锁,每个账户都使用一把锁
    pthread_mutex_t mut;
} Account;

Account acct1 = {1, 100, PTHREAD_MUTEX_INITIALIZER};

int withdraw(Account* a, int money)
{
    //临界前上锁
    int ret;
    pthread_mutex_lock(&a->mut);
    if(a->banlance <= 0)
    {
        fprintf(stderr, "Error: not enough money!\n");
        pthread_mutex_unlock(&a->mut);
        ret = -1;
        goto end;
    }
    if(a->banlance >= money)
    {
        sleep(1);   //增大线程间切换的概率
        a->banlance -= money;
        ret = money;
        goto end;
    }
    ret = a->banlance;
    a->banlance = 0;
    //注意点1：每次函数的出口都要释放锁
end:
    pthread_mutex_unlock(&a->mut);
    return ret;
}

void* start_routine(void* args)
{
    int money = (int) args;
    int ret = withdraw(&acct1, money);
    if(ret != -1)
    {
        printf("0x%lx: withdraw %d\n", pthread_self(), ret);
    }
    return NULL;
}

int main()
{
    pthread_t tid[2];
    pthread_create(&tid[0], NULL, start_routine, (void*)100);
    pthread_create(&tid[1], NULL, start_routine, (void*)100);

    //直接传线程标号
    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);

    return 0;
}